﻿using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Auditing;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories;
using Microsoft.Extensions.Logging;
using Volo.Abp.Application.Services;
using EcoSystem.Enums;

namespace EcoSystem
{
    public class ConfigCategoryAppService : CrudAppService<
         ConfigCategory,
         ConfigCategoryDto,
         string,
         GetConfigCategoryInput,
         CreateOrUpdateConfigCategoryDto,
         CreateOrUpdateConfigCategoryDto>, IConfigCategoryAppService
    {
        private readonly IRepository<ConfigDefine, Guid> _defineRepository;
        private readonly IConfigSettingAppService _configSettingAppService;
        private readonly IConfigDefineAppService _defineAppService;
        private readonly IAuditingManager _auditingManager;
        public ConfigCategoryAppService(
           IAuditingManager auditingManager,
            IRepository<ConfigCategory, string> repository,
            IRepository<ConfigDefine, Guid> defineRepository,
            IConfigSettingAppService configSettingAppService,
            IConfigDefineAppService defineAppService)
            : base(repository)
        {
            _defineRepository = defineRepository;
            _configSettingAppService = configSettingAppService;
            _auditingManager = auditingManager;
            _defineAppService = defineAppService;
        }



        public override async Task<ConfigCategoryDto> CreateAsync(CreateOrUpdateConfigCategoryDto input)
        {
            var entity = ObjectMapper.Map<CreateOrUpdateConfigCategoryDto, ConfigCategory>(input);
            entity.SetId(input.Id);
            entity = await Repository.InsertAsync(entity, true);
            entity.DefineFields = null;
            if (input.DefineFields != null && input.DefineFields.Any())
            {
                await _defineAppService.ConfigDefineMultiEditAsync(new MultiConfigDefineDto()
                {
                    Category = entity.Id,
                    KeyConfigs = input.DefineFields.Select(x => new KeyConfigDefineDto()
                    {
                        Key = x.Key,
                        KeyName = x.KeyName,
                        ControlProperty = x.ControlProperty,
                        ControlType = x.ControlType,
                        DefaultValue = x.DefaultValue,
                        KeyType = x.KeyType,
                        SortIndex = x.SortIndex,
                        Id = x.Id
                    }).ToList()
                });
            }
            return await GetAsync(entity.Id);
        }

        public override async Task<ConfigCategoryDto> UpdateAsync(string id, CreateOrUpdateConfigCategoryDto input)
        {
            var entity = await Repository.FirstOrDefaultAsync(x => x.Id == id);
            if (entity == null)
            {
                throw new UserFriendlyException("需要修改的信息不存在");
            }
            entity = ObjectMapper.Map(input, entity);
            entity = await Repository.UpdateAsync(entity);
            entity.DefineFields = null;
            if (input.DefineFields == null)
            {
                input.DefineFields = new List<ConfigDefineDto>();
            }
            if (entity.ConfigType != ConfigType.Interface || input.DefineFields.Any())
            {
                await _defineAppService.ConfigDefineMultiEditAsync(new MultiConfigDefineDto()
                {
                    Category = entity.Id,
                    KeyConfigs = input.DefineFields.Select(x => new KeyConfigDefineDto()
                    {
                        Key = x.Key,
                        KeyName = x.KeyName,
                        ControlProperty = x.ControlProperty,
                        ControlType = x.ControlType,
                        DefaultValue = x.DefaultValue,
                        KeyType = x.KeyType,
                        SortIndex = x.SortIndex,
                        Id = x.Id
                    }).ToList()
                });
            };
            return await this.GetAsync(id);
        }

        public override async Task<ConfigCategoryDto> GetAsync(string id)
        {
            var entity = await Repository.GetAsync(id, false);
            if (entity == null)
            {
                throw new UserFriendlyException("配置定义信息不存在");
            }

            var items = await (await _defineRepository.GetQueryableAsync()).Where(x => x.Category == id).AsNoTracking().ToListAsync();
            var result = ObjectMapper.Map<ConfigCategory, ConfigCategoryDto>(entity);
            result.DefineFields = ObjectMapper.Map<List<ConfigDefine>, List<ConfigDefineDto>>(items);
            return result;
        }

        public override async Task<PagedResultDto<ConfigCategoryDto>> GetListAsync(GetConfigCategoryInput input)
        {
            var query = from a in (await Repository.GetQueryableAsync())
                        select a;
            query = query
                 .WhereIf(!string.IsNullOrEmpty(input.Key), x => x.Name.Contains(input.Key) || x.Id.Contains(input.Key))
                 .WhereIf(!string.IsNullOrEmpty(input.ModuleCode), x => x.ModuleScope.Contains(input.ModuleCode))
                 .WhereIf(input.ConfigType.HasValue, x => x.ConfigType == input.ConfigType)
                 .WhereIf(input.Level.HasValue, x => x.Level.HasFlag(input.Level))
                 .WhereIf(input.Usage.HasValue, x => x.Usage == input.Usage)
                 .WhereIf(input.Status.HasValue, x => x.Status == input.Status);
            var total = await query.CountAsync();
            var list = await query.OrderBy(x => x.CreationTime).Skip(input.SkipCount).Take(input.MaxResultCount).ToListAsync();

            var defineItems = await (await _defineRepository.GetQueryableAsync()).Where(x => x.Id != Guid.Empty).ToListAsync();
            var items = ObjectMapper.Map<List<ConfigCategory>, List<ConfigCategoryDto>>(list);
            items.ForEach(item =>
            {
                var fields = defineItems.Where(x => x.Category == item.Id).OrderBy(x => x.SortIndex).ToList();
                item.DefineFields = ObjectMapper.Map<List<ConfigDefine>, List<ConfigDefineDto>>(fields);
            });
            return new PagedResultDto<ConfigCategoryDto>
            {
                TotalCount = total,
                Items = items
            };
        }

        public override async Task DeleteAsync(string id)
        {
            var isExists = await Repository.AnyAsync(x => x.Id == id);
            if (!isExists)
            {
                return;
            }
            await _configSettingAppService.DeleteAllAsync(id);
            await Repository.DeleteAsync(id);
        }
    }
}
